package org.budo.compress.rar;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.List;

import org.budo.compress.AbstractCompressor;
import org.budo.support.lang.util.FileUtil;
import org.budo.support.lang.util.IoUtil;
import org.budo.support.lang.util.StringUtil;

import com.github.junrar.Archive;
import com.github.junrar.rarfile.FileHeader;

import lombok.extern.slf4j.Slf4j;

/**
 * @author limingwei
 */
@Slf4j
public class RarCompressor extends AbstractCompressor {
    @Override
    public void compress(File from, File to) {
        throw new RuntimeException();
    }

    @Override
    public void decompress(File from, File to) {
        if (null == from || from.length() < 1) {
            log.error("#31 from file is null or empty, from=" + from);
            return;
        }

        Archive archive = null;
        try {
            archive = new Archive(new FileInputStream(from));

            if (archive.isEncrypted()) {
                throw new RuntimeException("#27 archive.isEncrypted, from=" + from);
            }

            List<FileHeader> fileHeaders = archive.getFileHeaders();
            for (FileHeader fileHeader : fileHeaders) {
                if (fileHeader.isEncrypted()) {
                    IoUtil.close(archive);
                    throw new RuntimeException("#27 fileHeader.isEncrypted, fileHeader=" + fileHeader + ", from=" + from);
                }

                String fileName = fileHeader.getFileNameString();
                if (StringUtil.isEmpty(fileName)) {
                    log.error("#44 fileName is empty, fileName=" + fileName + ", fileHeader=" + fileHeader + ", from=" + from);
                    continue;
                }

                File toFile = new File(to.getCanonicalPath() + File.separator + fileName);

                if (fileHeader.isDirectory()) {
                    toFile.mkdirs();
                    continue;
                }

                FileUtil.createNewFile(toFile);
                FileOutputStream fileOutputStream = new FileOutputStream(toFile);

                archive.extractFile(fileHeader, fileOutputStream);
                IoUtil.close(fileOutputStream);
            }
        } catch (Throwable e) {
            throw e instanceof RuntimeException //
                    ? (RuntimeException) e //
                    : new RuntimeException(e);
        } finally {
            IoUtil.close(archive);
        }
    }
}